package com.googlecode.openauth.client;

import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import com.googlecode.openauth.entity.ActionInfo;
import com.googlecode.openauth.entity.AreaInfo;
import com.googlecode.openauth.entity.MenuInfo;
import com.googlecode.openauth.entity.ResourceInfo;
import com.googlecode.openauth.entity.UserInfo;
import com.googlecode.openauth.exception.ValidateException;
import com.googlecode.openauth.mapper.ActionMapper;
import com.googlecode.openauth.mapper.AreaMapper;
import com.googlecode.openauth.mapper.LoginMapper;
import com.googlecode.openauth.mapper.MenuMapper;
import com.googlecode.openauth.mapper.ResourceMapper;
import com.googlecode.openauth.util.MD5;
/**
 * 此类用于验证用户信息,并提供取回某用户权限信息的方法.
 * 由于此类将提供给业务系统使用,且不涉及到对数据库的写操作.
 * 因此在实现时为了简单可不用Spring,
 * 直接使用Mybatis或直接使用jdbc读取数据库数据.
 * 
 **/
public class UserPrivilege {
	private int currentUserId = -1;
	private String currentUsername = null;
	private boolean isLogin = false;
	private DataSource dataSource = null;
	private static SqlSessionFactory sqlSessionFactory = null;
	private SqlSession sqlSession = null;
	private ActionMapper actionMapper = null;
	private AreaMapper areaMapper = null;
	private LoginMapper loginMapper = null;
	private MenuMapper menuMapper = null;
	private ResourceMapper resMapper = null;
	
	/**
	 * 此方法读取一个默认的数据库配置文件,以备验证用户或读取权限时使用.
	 * @throws IOException 
	 **/
	public UserPrivilege() throws IOException {
		Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		sqlSession = sqlSessionFactory.openSession();
		actionMapper = sqlSession.getMapper(ActionMapper.class);
		areaMapper = sqlSession.getMapper(AreaMapper.class);
		loginMapper = sqlSession.getMapper(LoginMapper.class);
		menuMapper = sqlSession.getMapper(MenuMapper.class);
		resMapper = sqlSession.getMapper(ResourceMapper.class);
	}

	/**
	 * 为了与Spring的一般用法兼容，增加此接口。
	 **/
	public UserPrivilege(DataSource dataSource) {
		this.dataSource = dataSource;
		TransactionFactory transactionFactory = new JdbcTransactionFactory();
		Environment environment = new Environment("development", transactionFactory, dataSource);
		Configuration configuration = new Configuration(environment);
		configuration.addMappers("com.googlecode.openauth.mapper");
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
		sqlSession = sqlSessionFactory.openSession();
		actionMapper = sqlSession.getMapper(ActionMapper.class);
		areaMapper = sqlSession.getMapper(AreaMapper.class);
		loginMapper = sqlSession.getMapper(LoginMapper.class);
		menuMapper = sqlSession.getMapper(MenuMapper.class);
		resMapper = sqlSession.getMapper(ResourceMapper.class);
	}
	
	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	
	public DataSource getDataSource() {
		return this.dataSource;
	}
	
	/**
	 * 根据参数连接到数据库.
	 * databseVendor可接受的值为MSSQL2000,MSSQL2005/2008,ORACLE,MYSQL,etc ...
	 **/
	public UserPrivilege(String databaseVendor,String jdbcURL,String dbUser,String password) {
		//设置连接属性
		Properties properties = new Properties();
		if(databaseVendor.equalsIgnoreCase("ORACLE"))
			properties.setProperty("driver", "oracle.jdbc.driver.OracleDriver");
		else if(databaseVendor.equalsIgnoreCase("MYSQL"))
			properties.setProperty("driver", "com.mysql.jdbc.Driver");
		else if(databaseVendor.equalsIgnoreCase("MSSQL"))
			properties.setProperty("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver");
		properties.setProperty("url", jdbcURL);
		properties.setProperty("username", dbUser);
		properties.setProperty("password", password);
		PooledDataSourceFactory dataSourceFactory = new PooledDataSourceFactory();
		dataSourceFactory.setProperties(properties);
		DataSource dataSource = dataSourceFactory.getDataSource();
		TransactionFactory transactionFactory = new JdbcTransactionFactory();
		Environment environment = new Environment("development", transactionFactory, dataSource);
		Configuration configuration = new Configuration(environment);
		configuration.addMappers("com.googlecode.openauth.mapper");
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
		sqlSession = sqlSessionFactory.openSession();
		actionMapper = sqlSession.getMapper(ActionMapper.class);
		areaMapper = sqlSession.getMapper(AreaMapper.class);
		loginMapper = sqlSession.getMapper(LoginMapper.class);
		menuMapper = sqlSession.getMapper(MenuMapper.class);
		resMapper = sqlSession.getMapper(ResourceMapper.class);
	}
	
	/**
	 * 验证用户名与口令是否符合.注意这里仅验证合法性即可.不需要读出用户的权限信息.
	 * 
	 **/
	public boolean validate(String username,String password) 
			throws ValidateException {
		//存取此用户名以备其它方法使用.
		currentUsername = username;
		MD5 md5 = new MD5();
		String md5Pwd = md5.getMD5ofStr(password);
		UserInfo user = loginMapper.getUser(username);
		if (user != null) {
			if(user.getPassword().equalsIgnoreCase(md5Pwd)) {
				currentUserId = user.getUserId();
				isLogin = true;
				return isLogin;
			}
		}
		currentUserId = -1;
		isLogin = false;
		throw new ValidateException("登录验证失败");
	}
	
	/**
	 * 取当前用户已授权的资源信息
	 * @throws ValidateException 
	 * 
	 **/
	public List<ResourceInfo> getResources() throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		List<ResourceInfo> resList = resMapper.getResesByUserId(currentUserId);
		return resList;
	}
	
	/**
	 * 取出当前用户已授权的所有下级菜单数据.
	 * @throws ValidateException 
	 **/
	public List<MenuInfo> getMenus() throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		List<MenuInfo> menuList = menuMapper.getMenusByUserId(currentUserId);
		return menuList;
	}
	
	/**
	 * 取出当前用户已授权的区域数据.此外仅取出当前用户下一级菜单信息.
	 * @throws ValidateException 
	 **/
	public List<MenuInfo> getOneLevelMenus() throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		List<MenuInfo> menuList = menuMapper.getOneLevelMenusByUserId(currentUserId);
		return menuList;
	}
	
	/**
	 * 取出某一菜单下的当前用户已授权的子菜单.
	 * @throws ValidateException 
	 **/
	public List<MenuInfo> getChildrenMenus(String parentMenuUUID) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("uuid", parentMenuUUID);
		List<MenuInfo> menuList = menuMapper.getMenuByUserIdMenuParentUuid(map);
		return menuList;
	}
	
	/**
	 * 取出当前用户已授权的Action信息.
	 * @throws ValidateException 
	 **/
	public List<ActionInfo> getActions() throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		List<ActionInfo> actionList = actionMapper.getActionsByUserId(currentUserId);
		return actionList;
	}
	
	/**
	 * 取出当前用户已授权的区域数据.此外取出的所有下级区域的信息.
	 * @throws ValidateException 
	 **/
	public List<AreaInfo> getAreas() throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		List<AreaInfo> areaList = areaMapper.getAreasByUserId(currentUserId);
		return areaList;
	}
	
	/**
	 * 取出当前用户已授权的区域数据.此外仅取出当前用户下一级区域信息.
	 * @throws ValidateException 
	 **/
	public List<AreaInfo> getOneLevelAreas() throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		List<AreaInfo> areaList = areaMapper.getOneLevelAreasByUserId(currentUserId);
		return areaList;
	}
	
	/**
	 * 取出某一区域下的当前用户已授权的子区域.
	 * @throws ValidateException 
	 **/
	public List<AreaInfo> getChildrenAreas(String parentAreaUUID) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("uuid", parentAreaUUID);
		List<AreaInfo> areaList = areaMapper.getAreaByUserIdAreaParentUuid(map);
		return areaList;
	}
	
	/**
	 * 判断当前用户是否有指定actionId的权限
	 * @throws ValidateException 
	 **/
	public boolean validateUserActionId(int actionId) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, Integer> map = new HashMap<String, Integer>();
		map.put("userId", currentUserId);
		map.put("actionId", actionId);
		ActionInfo res = actionMapper.getActionByUserIdActionId(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否有指定actionName的权限
	 * @throws ValidateException 
	 **/
	public boolean validateUserActionName(String actionName) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("actionName", actionName);
		ActionInfo res = actionMapper.getActionByUserIdActionName(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否有指定action uuid的权限
	 * @throws ValidateException 
	 **/
	public boolean validateUserActionUuid(String uuid) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("uuid", uuid);
		ActionInfo res = actionMapper.getActionByUserIdActionUuid(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否拥有指定区域ID的权限
	 * @throws ValidateException 
	 **/
	public boolean validateUserAreaId(int areaId) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, Integer> map = new HashMap<String, Integer>();
		map.put("userId", currentUserId);
		map.put("areaId", areaId);
		AreaInfo res = areaMapper.getAreaByUserIdAreaId(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否拥有指定区域名称的权限
	 * @throws ValidateException 
	 **/
	public boolean validateUserAreaName(String areaName) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("areaName", areaName);
		AreaInfo res = areaMapper.getAreaByUserIdAreaName(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否拥有指定区域UUID的权限
	 * @throws ValidateException 
	 **/
	public boolean validateUserAreaUuid(String uuid) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("uuid", uuid);
		AreaInfo res = areaMapper.getAreaByUserIdAreaUuid(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否拥有指定菜单ID的权限
	 * @throws ValidateException 
	 */
	public boolean validateUserMenuId(int menuId) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, Integer> map = new HashMap<String, Integer>();
		map.put("userId", currentUserId);
		map.put("menuId", menuId);
		MenuInfo res = menuMapper.getMenuByUserIdMenuId(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否拥有指定菜单名称的权限
	 * @throws ValidateException 
	 */
	public boolean validateUserMenuName(String menuName) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("menuName", menuName);
		MenuInfo res = menuMapper.getMenuByUserIdMenuName(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否拥有指定菜单UUID的权限
	 * @throws ValidateException 
	 */
	public boolean validateUserMenuUuid(String uuid) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("uuid", uuid);
		MenuInfo res = menuMapper.getMenuByUserIdMenuUuid(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否拥有指定资源ID的权限
	 * @throws ValidateException 
	 **/
	public boolean validateUserResId(int resId) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, Integer> map = new HashMap<String, Integer>();
		map.put("userId", currentUserId);
		map.put("resId", resId);
		ResourceInfo res = resMapper.getResByUserIdResId(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否拥有指定资源名称的权限
	 * @throws ValidateException 
	 **/
	public boolean validateUserResName(String resName) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("resName", resName);
		ResourceInfo res = resMapper.getResByUserIdResName(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 判断当前用户是否拥有指定资源UUID的权限
	 * @throws ValidateException 
	 **/
	public boolean validateUserResUuid(String uuid) throws ValidateException {
		if (!isLogin)
			throw new ValidateException("用户未登录");
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", String.valueOf(currentUserId));
		map.put("uuid", uuid);
		ResourceInfo res = resMapper.getResByUserIdResUuid(map);
		if (res == null)
			return false;
		else
			return true;
	}
	
	/**
	 * 取当前用户名
	 **/
	public String getCurrentUsername() {
		return currentUsername;
	}
	
	/**
	 * 取sqlSessionFactory
	 **/
	public static SqlSessionFactory getSqlSessionFactory() {
		return sqlSessionFactory;
	}
}